home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / uupc11ys.zip / MAIL / ALIAS.C < prev    next >
C/C++ Source or Header  |  1993-04-10  |  16KB  |  418 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    alias.c                                                         */
  3. /*                                                                    */
  4. /*    Smart routing and alias routines for pcmail.                    */
  5. /*                                                                    */
  6. /*    Copyright (C) 1989 Andrew H. Derbyshire                         */
  7. /*                                                                    */
  8. /*    Additional code                                                 */
  9. /*       Copyright (c) Richard H. Lamb 1985, 1986, 1987               */
  10. /*       Changes Copyright (c) Stuart Lynne 1987                      */
  11. /*                                                                    */
  12. /*    Updates:                                                        */
  13. /*                                                                    */
  14. /*    02 Oct 89   Alter large strings/structures to use               */
  15. /*                malloc()/free()                              ahd    */
  16. /*    08 Feb 90   Correct failure of ExtractAddress to return         */
  17. /*                non-names                                    ahd    */
  18. /*    18 Mar 90   Move checkname() and associated routines into       */
  19. /*                hostable.c                                   ahd    */
  20. /*    22 Apr 90   Modify user_at_node to correctly handle .UUCP       */
  21. /*                alias on local host.                         ahd    */
  22. /*--------------------------------------------------------------------*/
  23.  
  24. /*
  25.  *    $Id: ALIAS.C 1.3 1993/04/11 00:33:05 ahd Exp $
  26.  *
  27.  *    $Log: ALIAS.C $
  28.  * Revision 1.3  1993/04/11  00:33:05  ahd
  29.  * Global edits for year, TEXT, etc.
  30.  *
  31.  * Revision 1.2  1992/11/22  21:06:14  ahd
  32.  * Use strpool for memory allocation
  33.  *
  34.  */
  35.  
  36. #include <ctype.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <sys/types.h>
  41.  
  42. #ifndef __TURBOC__
  43. #include <search.h>
  44. #endif
  45.  
  46. #include "lib.h"
  47. #include "hostable.h"
  48. #include "security.h"
  49. #include "usertabl.h"
  50. #include "hlib.h"
  51. #include "alias.h"
  52. #include "address.h"
  53.  
  54. static size_t AliasCount = 0;
  55.  
  56. static struct AliasTable *alias = NULL;
  57.  
  58. int nickcmp( const void *a, const void *b );
  59.  
  60. static size_t LoadAliases( void ) ;
  61.  
  62. currentfile();
  63.  
  64. /*--------------------------------------------------------------------*/
  65. /*    I n i t R o u t e r                                             */
  66. /*                                                                    */
  67. /*    Verify, initialize the global routing data                      */
  68. /*--------------------------------------------------------------------*/
  69.  
  70. boolean InitRouter()
  71. {
  72.    boolean success = TRUE;       /* Assume the input data is good       */
  73.    struct HostTable *Hptr;
  74.  
  75. /*--------------------------------------------------------------------*/
  76. /*          Verify that the user gave us a good name server           */
  77. /*--------------------------------------------------------------------*/
  78.  
  79.    Hptr = checkreal(E_mailserv);
  80.    if (Hptr == BADHOST)
  81.    {
  82.       printmsg(0,"mail server '%s' must be listed in SYSTEMS file",
  83.          E_mailserv);
  84.       success = FALSE;
  85.    }
  86.    else if (Hptr->hstatus == localhost)  /* local system?     */
  87.    {
  88.       printmsg(0,"'%s' is name of this host and cannot be mail server",
  89.             E_mailserv);
  90.       success = FALSE;
  91.    }
  92.  
  93. /*--------------------------------------------------------------------*/
  94. /*                          Return to caller                          */
  95. /*--------------------------------------------------------------------*/
  96.  
  97.    return success;
  98. } /* InitRouter */
  99.  
  100. /*--------------------------------------------------------------------*/
  101. /*    E x t r a c t N a m e                                           */
  102. /*                                                                    */
  103. /*    Returns full name of user, and returns address if name          */
  104. /*    is not available.                                               */
  105. /*--------------------------------------------------------------------*/
  106.  
  107. void ExtractName(char *result, char *column)
  108. {
  109.       static int recursion = 0;
  110.  
  111.       recursion++;
  112.  
  113.       printmsg((recursion > 2) ? 1:8,
  114.             "ExtractName: Getting name from '%s'",column);
  115.  
  116.       ExtractAddress(result, column, TRUE);  /* Get the full name    */
  117.       if (!strlen(result))       /* Did we get the name?             */
  118.       {                          /* No --> Get the e-mail address    */
  119.          char addr[MAXADDR];
  120.          char path[MAXADDR];
  121.          char node[MAXADDR];
  122.          char *fullname;
  123.  
  124.          ExtractAddress(addr,column, FALSE);
  125.          user_at_node(addr,path,node,result);
  126.                                  /* Reduce address to basics */
  127.          fullname = AliasByAddr(node,result);
  128.          if (fullname == NULL)
  129.          {
  130.             strcat(result,"@");
  131.             strcat(result,node);
  132.          }
  133.          else
  134.             strcpy(result,fullname);
  135.       }
  136.  
  137.       printmsg((recursion > 2) ? 1: 8,"ExtractName: name is '%s'",result);
  138.  
  139.       recursion--;
  140.  
  141.       return;
  142. }  /*ExtractName*/
  143.  
  144. /*--------------------------------------------------------------------*/
  145. /*    B u i l d A d d r e s s                                         */
  146. /*                                                                    */
  147. /*    Builds a standard address format, with aliasing as              */
  148. /*    required.                                                       */
  149. /*--------------------------------------------------------------------*/
  150.  
  151. void BuildAddress(char *result, const char *input)
  152. {
  153.    char addr[MAXADDR];
  154.    char name[MAXADDR];
  155.    char user[MAXADDR];
  156.    char path[MAXADDR];
  157.    char node[MAXADDR];
  158.    char *fulladdr;
  159.  
  160. /*--------------------------------------------------------------------*/
  161. /*   It must be a real address, possibly with a name attached; get    */
  162. /*   the address portion, break the address into user and node, and   */
  163. /*   then see if we know the person by address                        */
  164. /*--------------------------------------------------------------------*/
  165.  
  166.       ExtractAddress(addr,input,FALSE);   /* Get user e-mail addr    */
  167.       user_at_node(addr,path,node,user);  /* Break address down      */
  168.  
  169.       fulladdr = AliasByAddr(node,user);  /* Alias for the address?  */
  170.       if (fulladdr != NULL)            /* Yes --> Use it             */
  171.       {
  172.          strcpy(result,fulladdr);
  173.          return;
  174.       } /* if */
  175.  
  176. /*--------------------------------------------------------------------*/
  177. /*   We don't know the address yet; get the name the user provided,   */
  178. /*   and then normalize the address                                   */
  179. /*--------------------------------------------------------------------*/
  180.  
  181.       ExtractAddress(name,input,TRUE);    /* Also get their name     */
  182.  
  183.       if (strlen(name))             /* Did we find a name for user?  */
  184.       {                             /* Yes --> Return it             */
  185.          char *s = strchr(node, '.');
  186.          if ((s == NULL) || equalni( s, ".UUCP", 5))
  187.                                     /* Simple name or UUCP domain?   */
  188.          {                          /* Yes--> Use original address   */
  189.             size_t pathlen = strlen(path);/* Save len of orig path   */
  190.             if ((pathlen > strlen(addr)) &&
  191.                 (!equal(node,path)) && /* Target not a known host?   */
  192.                 equaln(addr,path, strlen(path)) && /* & host starts  */
  193.                 (addr[pathlen] == '!'))   /* ...the address?         */
  194.                fulladdr = &addr[pathlen + 1];   /* Yes --> Drop it   */
  195.             else
  196.                fulladdr = addr;  /* No --> Use full address          */
  197.             sprintf(result,"(%s) %s", name, addr);
  198.          } /* (strchr(node, '.') == NULL) */
  199.          else                    /* No --> Use RFC-822 format        */
  200.             sprintf(result,"\"%s\" <%s@%s>", name, user, node);
  201.       } /* if strlen(name) */
  202.       else
  203.          strcpy(result,addr);    /* No name, just use the original   */
  204. } /* BuildAddress */
  205.  
  206.  
  207. /*--------------------------------------------------------------------*/
  208. /*    A l i a s B y N i c k                                           */
  209. /*                                                                    */
  210. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  211. /*    if alias found and has address, otherwise FALSE.                */
  212. /*--------------------------------------------------------------------*/
  213.  
  214. char *AliasByNick(const char *nick)
  215. {
  216.    int   upper;
  217.    int   lower;
  218.  
  219.    if (!AliasCount)
  220.       AliasCount = LoadAliases();
  221.  
  222.    upper = AliasCount - 1;
  223.    lower = 0;
  224.  
  225.    while (upper >= lower)
  226.    {
  227.       int midpoint;
  228.       int hit;
  229.  
  230.       midpoint = ( upper + lower ) / 2;
  231.       hit = stricmp(nick,alias[midpoint].anick);
  232.       if (!hit)
  233.          return alias[midpoint].afull;
  234.       if ( hit > 0 )
  235.          lower = midpoint + 1;
  236.       else
  237.          upper = midpoint - 1;
  238.    }
  239.    return NULL;
  240. }
  241.  
  242.  
  243. /*--------------------------------------------------------------------*/
  244. /*    A l i a s B y A d d r                                           */
  245. /*                                                                    */
  246. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  247. /*    if alias found and has address, otherwise FALSE                 */
  248. /*--------------------------------------------------------------------*/
  249.  
  250. char *AliasByAddr(const char *node, const char *user)
  251. {
  252.    size_t current = 0;
  253.  
  254.    if (!AliasCount)
  255.       AliasCount = LoadAliases();
  256.  
  257.    while (current < AliasCount)
  258.    {
  259.       int hit;
  260.  
  261.       hit = stricmp(node,alias[current].anode);
  262.       if (!hit)
  263.       {
  264.          hit = stricmp(user,alias[current].auser);
  265.          if (!hit)
  266.             return alias[current].afull;
  267.       }
  268.       current++;
  269.    }
  270.    return NULL;
  271.  
  272. }
  273.  
  274.  
  275. /*--------------------------------------------------------------------*/
  276. /*    L o a d A l i a s e s                                           */
  277. /*                                                                    */
  278. /*    Initializes the address alias table; returns number of aliases  */
  279. /*    loaded                                                          */
  280. /*--------------------------------------------------------------------*/
  281.  
  282. size_t LoadAliases(void)
  283. {
  284.    FILE *ff;
  285.    char buf[BUFSIZ];
  286.    char *token;
  287.    size_t   elements = 0;
  288.    size_t   max_elements = UserElements + 20;
  289.    size_t   subscript;
  290.    struct AliasTable *hit;           /* temporary pointer for searching  */
  291.    struct AliasTable target;
  292.  
  293.  
  294.    checkuser( E_mailbox ); /* Force the table to be loaded           */
  295.    alias = calloc(max_elements, sizeof(*alias));
  296.    checkref(alias);
  297.  
  298. /*--------------------------------------------------------------------*/
  299. /*                   Actually load the alias table                    */
  300. /*--------------------------------------------------------------------*/
  301.  
  302.    if (E_aliases != NULL )    /* Did the user specify aliases file?  */
  303.    {
  304.  
  305.       ff = FOPEN(E_aliases, "r",TEXT_MODE);
  306.       if (ff == NULL)
  307.       {
  308.          printerr(E_aliases);
  309.          return elements;
  310.       } /* if */
  311.  
  312.       while (! feof(ff))
  313.       {
  314.          if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  315.             break;                  /* Exit if end of file              */
  316.          token = strtok(buf," \t\n");
  317.          if (token == NULL)         /* Any data?                        */
  318.             continue;               /* No --> read another line         */
  319.          if (token[0] == '#')
  320.             continue;                  /* Line is a comment; loop again */
  321.  
  322.          /* Add the alias to the table.  Note that we must add the nick */
  323.          /* to the table ourselves (rather than use lsearch) because    */
  324.          /* we must make a copy of the string; the *token we use for    */
  325.          /* the search is in the middle of our I/O buffer!              */
  326.          /*
  327.          /* I was burned, _you_ have been warned.                       */
  328.  
  329.          target.anick = token;
  330.  
  331.          hit = (void *) lfind(&target, alias, &elements , sizeof(alias[0]),
  332.              nickcmp);
  333.          if (hit == NULL)
  334.          {
  335.             char node[MAXADDR];
  336.             char user[MAXADDR];
  337.             char path[MAXADDR];
  338.             char addr[MAXADDR];
  339.             char *eos;
  340.  
  341.             if (elements == max_elements)
  342.             {
  343.                 max_elements = max_elements * 2;
  344.                 alias = realloc(alias, max_elements * sizeof(*alias));
  345.                 checkref(alias);
  346.             }
  347.  
  348.             alias[elements].anick = newstr(token);
  349.             token = strtok(NULL,"");    /* Get rest of string         */
  350.  
  351.             while ( strlen(token) && isspace(*token))
  352.                token++;
  353.             eos = token + strlen(token) - 1;
  354.             while ( strlen(token) && isspace(*eos))
  355.             {
  356.                *eos = '\0';
  357.                eos--;
  358.             }
  359.  
  360.             alias[elements].afull = newstr(token);
  361.             ExtractAddress(addr,alias[elements].afull,FALSE);
  362.             user_at_node(addr,path,node,user);
  363.             alias[elements].anode = newstr(node);
  364.             alias[elements].auser = newstr(user);
  365.             elements += 1;
  366.          }
  367.          else
  368.             printmsg(0,"LoadAliases: Duplicate alias '%s' in table",token);
  369.       }
  370.       fclose(ff);
  371.    } /* if (E_aliases != NULL ) */
  372.  
  373. /*--------------------------------------------------------------------*/
  374. /*           Add the local users as final aliases in table            */
  375. /*--------------------------------------------------------------------*/
  376.  
  377.    alias = realloc(alias, (elements + UserElements) * sizeof(*alias));
  378.                               /* Resize table to final known size    */
  379.    checkref(alias);
  380.  
  381.    for ( subscript = 0; subscript < UserElements; subscript++, elements++)
  382.    {
  383.       alias[elements].anick = "";   /* No nickname, only good for addr  */
  384.       if (bflag[F_BANG])
  385.          sprintf(buf, "(%s) %s!%s",
  386.                users[subscript].realname, E_fdomain,
  387.                users[subscript].uid);
  388.       else
  389.          sprintf(buf, "\"%s\" <%s@%s>", users[subscript].realname,
  390.                users[subscript].uid, E_fdomain );
  391.       alias[elements].afull = newstr(buf);
  392.       alias[elements].anode = E_nodename;
  393.       alias[elements].auser = users[subscript].uid;
  394.    } /* for */
  395.  
  396. /*--------------------------------------------------------------------*/
  397. /*                         Now sort the table                         */
  398. /*--------------------------------------------------------------------*/
  399.  
  400.    qsort(alias, elements ,sizeof(alias[0]) , nickcmp);
  401.  
  402.    return (elements) ;
  403. } /*LoadAliases*/
  404.  
  405.  
  406. /*--------------------------------------------------------------------*/
  407. /*   n i c k c m p                                                    */
  408. /*                                                                    */
  409. /*   Accepts indirect pointers to two strings and compares them using */
  410. /*   stricmp (case insensitive string compare)                        */
  411. /*--------------------------------------------------------------------*/
  412.  
  413. int nickcmp( const void *a, const void *b )
  414. {
  415.    return stricmp(((struct AliasTable *)a)->anick,
  416.          ((struct AliasTable *)b)->anick);
  417. }  /*nickcmp*/
  418.